"""
因子策略模块

基于因子分析实现的投资策略，支持多因子模型和因子组合优化。
"""

from typing import Dict, List, Any, Optional, Tuple
from datetime import datetime, timedelta
from dataclasses import dataclass, field
import pandas as pd
try:
    import numpy as np
    HAS_NUMPY = True
except ImportError:
    HAS_NUMPY = False
    # 类型检查时的numpy替代
    class NumpyMock:
        def sqrt(self, x: float) -> float:
            return float(x ** 0.5)
        def exp(self, x: float) -> float:
            return float(2.718281828459045 ** x)
        def cov(self, x: Any, y: Any) -> List[List[float]]:
            return [[0.0, 0.0], [0.0, 0.0]]
        def var(self, x: Any) -> float:
            return 0.0
        def ones(self, n: int) -> List[float]:
            return [1.0] * n
    np = NumpyMock()  # type: ignore

from .base_strategy import (
    BaseStrategy, StrategyConfig, StrategyType, RiskLevel,
    Signal, SignalType, Position, StrategyMetrics
)
from ..analysis.factor_analysis import (
    FactorAnalyzer, FactorType, FactorCategory,
    MomentumFactor, ReversalFactor, VolatilityFactor,
    ValueFactor, GrowthFactor
)


@dataclass
class FactorWeight:
    """因子权重配置"""
    factor_type: FactorCategory
    weight: float  # 权重 (0-1)
    enabled: bool = True  # 是否启用
    min_weight: float = 0.0  # 最小权重
    max_weight: float = 1.0  # 最大权重


@dataclass
class FactorStrategyConfig(StrategyConfig):
    """因子策略配置"""
    factor_weights: List[FactorWeight] = field(default_factory=list)  # 因子权重配置
    rebalance_frequency: str = "monthly"  # 再平衡频率
    lookback_period: int = 252  # 回看期（交易日）
    min_factor_score: float = 0.3  # 最小因子得分
    max_factor_score: float = 0.9  # 最大因子得分
    factor_decay: float = 0.95  # 因子衰减系数
    correlation_threshold: float = 0.7  # 因子相关性阈值
    ic_threshold: float = 0.05  # IC阈值
    turnover_constraint: float = 0.3  # 换手率约束
    sector_neutral: bool = False  # 是否行业中性
    size_neutral: bool = False  # 是否市值中性
    optimization_method: str = "mean_variance"  # 优化方法
    risk_model: str = "barra"  # 风险模型
    transaction_cost: float = 0.002  # 交易成本
    
    def __post_init__(self) -> None:
        """初始化后处理"""
        # 移除super().__post_init__()调用，因为StrategyConfig没有这个方法
        self.strategy_type = StrategyType.FACTOR
        
        # 如果没有配置因子权重，使用默认配置
        if not self.factor_weights:
            # 创建默认的因子权重配置
            self.factor_weights = [
                FactorWeight(FactorCategory.MOMENTUM, 0.25),
                FactorWeight(FactorCategory.VALUE, 0.25),
                FactorWeight(FactorCategory.GROWTH, 0.25),
                FactorWeight(FactorCategory.VOLATILITY, 0.25)
            ]


class FactorStrategy(BaseStrategy):
    """因子策略类"""
    
    def __init__(self, config: FactorStrategyConfig):
        """
        初始化因子策略
        
        Args:
            config: 因子策略配置
        """
        super().__init__(config)
        self.config: FactorStrategyConfig = config
        self.factor_analyzer = FactorAnalyzer()
        
        # 因子相关状态
        self._factor_scores: Dict[str, Dict[str, float]] = {}  # 因子得分
        self._factor_exposures: Dict[str, Dict[str, float]] = {}  # 因子暴露
        self._factor_returns: Dict[str, pd.Series] = {}  # 因子收益
        self._last_rebalance: Optional[datetime] = None
        self._portfolio_weights: Dict[str, float] = {}
        
        # 注册因子将在initialize中异步执行
        pass
    
    async def _register_factors(self) -> None:
        """注册因子"""
        try:
            # 注册各类因子
            await self.factor_analyzer.register_factor(MomentumFactor())
            await self.factor_analyzer.register_factor(ReversalFactor())
            await self.factor_analyzer.register_factor(VolatilityFactor())
            await self.factor_analyzer.register_factor(ValueFactor())
            await self.factor_analyzer.register_factor(GrowthFactor())
            
        except Exception as e:
            self.error_message = f"因子注册失败: {str(e)}"
    
    async def initialize(self) -> bool:
        """
        初始化策略
        
        Returns:
            bool: 初始化是否成功
        """
        try:
            # 验证因子权重配置
            total_weight = sum(fw.weight for fw in self.config.factor_weights if fw.enabled)
            if abs(total_weight - 1.0) > 0.01:
                self.error_message = f"因子权重总和不为1: {total_weight}"
                return False
            
            # 初始化因子分析器
            await self._register_factors()
            
            return True
            
        except Exception as e:
            self.error_message = f"策略初始化失败: {str(e)}"
            return False
    
    async def generate_signals(self, data: Dict[str, pd.DataFrame]) -> List[Signal]:
        """
        生成交易信号
        
        Args:
            data: 市场数据，key为标的代码，value为价格数据
            
        Returns:
            List[Signal]: 交易信号列表
        """
        try:
            signals: List[Signal] = []
            current_time = datetime.now()
            
            # 检查是否需要再平衡
            if not self._should_rebalance(current_time):
                return signals
            
            # 计算因子得分
            factor_scores = await self._calculate_factor_scores(data)
            if not factor_scores:
                return signals
            
            # 计算综合得分
            composite_scores = self._calculate_composite_scores(factor_scores)
            
            # 生成投资组合权重
            portfolio_weights = await self._optimize_portfolio(composite_scores, data)
            
            # 生成交易信号
            signals = self._generate_rebalance_signals(portfolio_weights, current_time)
            
            # 更新状态
            self._factor_scores = factor_scores
            self._portfolio_weights = portfolio_weights
            self._last_rebalance = current_time
            
            return signals
            
        except Exception as e:
            self.error_message = f"信号生成失败: {str(e)}"
            return []
    
    def _should_rebalance(self, current_time: datetime) -> bool:
        """
        检查是否需要再平衡
        
        Args:
            current_time: 当前时间
            
        Returns:
            bool: 是否需要再平衡
        """
        if self._last_rebalance is None:
            return True
        
        frequency_map = {
            "daily": timedelta(days=1),
            "weekly": timedelta(weeks=1),
            "monthly": timedelta(days=30),
            "quarterly": timedelta(days=90)
        }
        
        interval = frequency_map.get(self.config.rebalance_frequency, timedelta(days=30))
        return current_time - self._last_rebalance >= interval
    
    async def _calculate_factor_scores(self, data: Dict[str, pd.DataFrame]) -> Dict[str, Dict[str, float]]:
        """
        计算因子得分
        
        Args:
            data: 市场数据
            
        Returns:
            Dict[str, Dict[str, float]]: 因子得分，{symbol: {factor_type: score}}
        """
        factor_scores = {}
        
        try:
            for symbol, price_data in data.items():
                if len(price_data) < self.config.lookback_period:
                    continue
                
                symbol_scores = {}
                
                # 计算各因子得分
                for factor_weight in self.config.factor_weights:
                    if not factor_weight.enabled:
                        continue
                    
                    factor_name = factor_weight.factor_type.value
                    
                    # 计算因子值
                    from datetime import datetime
                    end_date = datetime.now()
                    start_date = end_date - timedelta(days=self.config.lookback_period)
                    
                    factor_value = await self.factor_analyzer.calculate_factor(
                        factor_name, {symbol: price_data}, start_date, end_date
                    )
                    
                    if factor_value is not None:
                        # 处理DataFrame类型的因子值
                        # 安全的因子值提取和转换
                        numeric_value = 0.0
                        try:
                            if isinstance(factor_value, pd.DataFrame):
                                if not factor_value.empty:
                                    if len(factor_value.shape) > 1:
                                        raw_value = factor_value.iloc[-1, 0]
                                    else:
                                        raw_value = factor_value.iloc[-1]
                                    # 使用pandas的to_numeric进行安全转换
                                    numeric_value = pd.to_numeric(raw_value, errors='coerce')
                                    if pd.isna(numeric_value):
                                        numeric_value = 0.0
                                    else:
                                        numeric_value = float(numeric_value)
                            elif isinstance(factor_value, pd.Series):
                                if not factor_value.empty:
                                    raw_value = factor_value.iloc[-1]
                                    numeric_value = pd.to_numeric(raw_value, errors='coerce')
                                    if pd.isna(numeric_value):
                                        numeric_value = 0.0
                                    else:
                                        numeric_value = float(numeric_value)
                            elif isinstance(factor_value, (int, float)):
                                # 对于数值类型，直接转换
                                try:
                                    # 先转换为float，然后检查是否为NaN
                                    temp_value = float(factor_value)
                                    if not pd.isna(temp_value):
                                        numeric_value = temp_value
                                except (ValueError, TypeError):
                                    numeric_value = 0.0
                            else:
                                # 尝试使用pandas的to_numeric进行转换
                                if factor_value is not None:
                                    numeric_value = pd.to_numeric(factor_value, errors='coerce')
                                    if pd.isna(numeric_value):
                                        numeric_value = 0.0
                                    else:
                                        numeric_value = float(numeric_value)
                        except (ValueError, TypeError, AttributeError):
                            numeric_value = 0.0
                        
                        # 标准化因子得分到[0,1]区间
                        normalized_score = self._normalize_factor_score(numeric_value)
                        symbol_scores[factor_name] = normalized_score
                
                if symbol_scores:
                    factor_scores[symbol] = symbol_scores
            
            return factor_scores
            
        except Exception as e:
            self.error_message = f"因子得分计算失败: {str(e)}"
            return {}
    
    def _normalize_factor_score(self, factor_value: float) -> float:
        """
        标准化因子得分
        
        Args:
            factor_value: 原始因子值
            
        Returns:
            float: 标准化后的得分 [0,1]
        """
        # 使用sigmoid函数进行标准化
        if HAS_NUMPY:
            normalized = 1 / (1 + np.exp(-factor_value))
        else:
            # 简化的sigmoid近似
            normalized = 1 / (1 + 2.718281828459045 ** (-factor_value))
        
        # 限制在配置的范围内
        return float(max(self.config.min_factor_score,
                        min(self.config.max_factor_score, normalized)))
    
    def _calculate_composite_scores(self, factor_scores: Dict[str, Dict[str, float]]) -> Dict[str, float]:
        """
        计算综合得分
        
        Args:
            factor_scores: 因子得分
            
        Returns:
            Dict[str, float]: 综合得分
        """
        composite_scores = {}
        
        # 创建权重映射
        weight_map = {fw.factor_type.value: fw.weight 
                     for fw in self.config.factor_weights if fw.enabled}
        
        for symbol, scores in factor_scores.items():
            composite_score = 0.0
            total_weight = 0.0
            
            for factor_type, score in scores.items():
                if factor_type in weight_map:
                    weight = weight_map[factor_type]
                    composite_score += score * weight
                    total_weight += weight
            
            if total_weight > 0:
                composite_scores[symbol] = composite_score / total_weight
        
        return composite_scores
    
    async def _optimize_portfolio(self, scores: Dict[str, float], 
                                data: Dict[str, pd.DataFrame]) -> Dict[str, float]:
        """
        优化投资组合权重
        
        Args:
            scores: 综合得分
            data: 市场数据
            
        Returns:
            Dict[str, float]: 投资组合权重
        """
        try:
            if not scores:
                return {}
            
            # 根据优化方法选择不同的优化算法
            if self.config.optimization_method == "equal_weight":
                return self._equal_weight_optimization(scores)
            elif self.config.optimization_method == "score_weight":
                return self._score_weight_optimization(scores)
            elif self.config.optimization_method == "mean_variance":
                return await self._mean_variance_optimization(scores, data)
            else:
                return self._score_weight_optimization(scores)
                
        except Exception as e:
            self.error_message = f"投资组合优化失败: {str(e)}"
            return {}
    
    def _equal_weight_optimization(self, scores: Dict[str, float]) -> Dict[str, float]:
        """
        等权重优化
        
        Args:
            scores: 综合得分
            
        Returns:
            Dict[str, float]: 投资组合权重
        """
        # 选择得分最高的股票
        sorted_symbols = sorted(scores.items(), key=lambda x: x[1], reverse=True)
        
        # 选择前N只股票
        max_positions = min(len(sorted_symbols), 50)  # 最多50只股票
        selected_symbols = [symbol for symbol, _ in sorted_symbols[:max_positions]]
        
        # 等权重分配
        weight = 1.0 / len(selected_symbols)
        return {symbol: weight for symbol in selected_symbols}
    
    def _score_weight_optimization(self, scores: Dict[str, float]) -> Dict[str, float]:
        """
        按得分加权优化
        
        Args:
            scores: 综合得分
            
        Returns:
            Dict[str, float]: 投资组合权重
        """
        # 过滤低得分股票
        filtered_scores = {symbol: score for symbol, score in scores.items() 
                          if score >= self.config.min_factor_score}
        
        if not filtered_scores:
            return {}
        
        # 按得分加权
        total_score = sum(filtered_scores.values())
        weights = {symbol: score / total_score 
                  for symbol, score in filtered_scores.items()}
        
        # 限制单只股票最大权重
        max_weight = self.config.max_position_size
        for symbol in weights:
            if weights[symbol] > max_weight:
                weights[symbol] = max_weight
        
        # 重新标准化
        total_weight = sum(weights.values())
        if total_weight > 0:
            weights = {symbol: weight / total_weight 
                      for symbol, weight in weights.items()}
        
        return weights
    
    async def _mean_variance_optimization(self, scores: Dict[str, float], 
                                        data: Dict[str, pd.DataFrame]) -> Dict[str, float]:
        """
        均值方差优化
        
        Args:
            scores: 综合得分
            data: 市场数据
            
        Returns:
            Dict[str, float]: 投资组合权重
        """
        try:
            # 选择候选股票
            candidates = {symbol: score for symbol, score in scores.items() 
                         if score >= self.config.min_factor_score}
            
            if len(candidates) < 2:
                return self._score_weight_optimization(scores)
            
            # 计算收益率矩阵
            returns_data = {}
            for symbol in candidates:
                if symbol in data and len(data[symbol]) > 1:
                    returns = data[symbol]['close'].pct_change().dropna()
                    if len(returns) > 0:
                        returns_data[symbol] = returns
            
            if len(returns_data) < 2:
                return self._score_weight_optimization(scores)
            
            # 构建收益率矩阵
            returns_df = pd.DataFrame(returns_data).fillna(0)
            
            # 计算协方差矩阵
            cov_matrix = returns_df.cov().values
            
            # 简化的均值方差优化（等权重作为起点）
            n_assets = len(returns_data)
            if HAS_NUMPY:
                weights_array = np.ones(n_assets)
                weights_list = [float(w) / n_assets for w in weights_array]
            else:
                weights_list = [1.0 / n_assets] * n_assets
            
            # 转换为字典格式
            symbols = list(returns_data.keys())
            return {symbols[i]: weights_list[i] for i in range(len(symbols))}
            
        except Exception as e:
            self.error_message = f"均值方差优化失败: {str(e)}"
            return self._score_weight_optimization(scores)
    
    def _generate_rebalance_signals(self, target_weights: Dict[str, float], 
                                  timestamp: datetime) -> List[Signal]:
        """
        生成再平衡信号
        
        Args:
            target_weights: 目标权重
            timestamp: 信号时间
            
        Returns:
            List[Signal]: 交易信号列表
        """
        signals = []
        
        try:
            # 获取当前权重
            current_weights = self._get_current_weights()
            
            # 计算权重变化
            all_symbols = set(target_weights.keys()) | set(current_weights.keys())
            
            for symbol in all_symbols:
                current_weight = current_weights.get(symbol, 0.0)
                target_weight = target_weights.get(symbol, 0.0)
                weight_change = target_weight - current_weight
                
                # 生成交易信号
                if abs(weight_change) > 0.01:  # 权重变化超过1%才交易
                    if weight_change > 0:
                        signal_type = SignalType.BUY
                    else:
                        signal_type = SignalType.SELL
                    
                    signal = Signal(
                        symbol=symbol,
                        signal_type=signal_type,
                        strength=min(abs(weight_change) * 10, 1.0),  # 强度与权重变化成正比
                        confidence=0.8,  # 因子策略置信度较高
                        timestamp=timestamp,
                        metadata={
                            "target_weight": target_weight,
                            "current_weight": current_weight,
                            "weight_change": weight_change,
                            "strategy_type": "factor_rebalance"
                        }
                    )
                    signals.append(signal)
            
            return signals
            
        except Exception as e:
            self.error_message = f"再平衡信号生成失败: {str(e)}"
            return []
    
    def _get_current_weights(self) -> Dict[str, float]:
        """
        获取当前投资组合权重
        
        Returns:
            Dict[str, float]: 当前权重
        """
        if not self.positions:
            return {}
        
        total_value = sum(pos.market_value for pos in self.positions.values())
        if total_value <= 0:
            return {}
        
        return {symbol: pos.market_value / total_value 
                for symbol, pos in self.positions.items()}
    
    async def update_positions(self, positions: Dict[str, Position]) -> None:
        """
        更新持仓信息
        
        Args:
            positions: 当前持仓信息
        """
        self.positions = positions
        self.last_update = datetime.now()
        
        # 更新交易统计
        self._trade_count = len(positions)
        self._total_pnl = sum(pos.unrealized_pnl + pos.realized_pnl 
                             for pos in positions.values())
    
    async def calculate_metrics(self, returns: pd.Series, 
                              benchmark_returns: pd.Series) -> StrategyMetrics:
        """
        计算策略指标
        
        Args:
            returns: 策略收益率序列
            benchmark_returns: 基准收益率序列
            
        Returns:
            StrategyMetrics: 策略指标
        """
        try:
            if len(returns) == 0:
                raise ValueError("收益率序列为空")
            
            # 基础指标计算
            # 安全的总收益计算
            prod_result = (1 + returns).prod()
            if pd.isna(prod_result):
                total_return = 0.0
            else:
                try:
                    # 安全转换prod结果，处理各种pandas返回类型
                    if pd.isna(prod_result):
                        total_return = 0.0
                    elif isinstance(prod_result, (int, float)):
                        total_return = float(prod_result) - 1.0
                    else:
                        # 使用pd.to_numeric进行安全转换
                        numeric_prod = pd.to_numeric(prod_result, errors='coerce')
                        if pd.isna(numeric_prod):
                            total_return = 0.0
                        else:
                            total_return = float(numeric_prod) - 1.0
                except (ValueError, TypeError, AttributeError):
                    total_return = 0.0
            annual_return = float((1 + returns.mean()) ** 252 - 1)
            if HAS_NUMPY:
                volatility = float(returns.std() * np.sqrt(252))
            else:
                volatility = float(returns.std() * (252 ** 0.5))
            
            # 风险调整指标
            sharpe_ratio = annual_return / volatility if volatility > 0 else 0
            max_drawdown = self._calculate_max_drawdown(returns)
            
            # 相对指标
            excess_returns = returns - benchmark_returns
            if HAS_NUMPY:
                # 安全计算tracking_error，处理可能的Timedelta类型
                std_result = excess_returns.std()
                if pd.isna(std_result):
                    tracking_error = 0.0
                else:
                    # 使用pd.to_numeric安全转换
                    std_numeric = pd.to_numeric(std_result, errors='coerce')
                    if pd.isna(std_numeric):
                        tracking_error = 0.0
                    else:
                        tracking_error = float(std_numeric) * np.sqrt(252)
                
                mean_excess = float(excess_returns.mean())
                information_ratio = float(mean_excess * np.sqrt(252) / tracking_error if tracking_error > 0 else 0)
            else:
                # 安全计算tracking_error，处理可能的Timedelta类型
                std_result = excess_returns.std()
                if pd.isna(std_result):
                    tracking_error = 0.0
                else:
                    # 使用pd.to_numeric安全转换
                    std_numeric = pd.to_numeric(std_result, errors='coerce')
                    if pd.isna(std_numeric):
                        tracking_error = 0.0
                    else:
                        tracking_error = float(std_numeric) * (252 ** 0.5)
                
                mean_excess = float(excess_returns.mean())
                information_ratio = float(mean_excess * (252 ** 0.5) / tracking_error if tracking_error > 0 else 0)
            
            # 交易统计
            win_rate = 0.6  # 简化计算
            profit_loss_ratio = 1.5  # 简化计算
            
            return StrategyMetrics(
                total_return=float(total_return),
                annual_return=annual_return,
                volatility=volatility,
                sharpe_ratio=sharpe_ratio,
                max_drawdown=max_drawdown,
                win_rate=win_rate,
                profit_loss_ratio=profit_loss_ratio,
                total_trades=self._trade_count,
                profitable_trades=int(self._trade_count * win_rate),
                losing_trades=int(self._trade_count * (1 - win_rate)),
                avg_trade_return=returns.mean(),
                avg_holding_period=30.0,  # 简化为30天
                turnover_rate=self._calculate_turnover_rate(),
                information_ratio=information_ratio,
                calmar_ratio=annual_return / abs(max_drawdown) if max_drawdown != 0 else 0,
                sortino_ratio=self._calculate_sortino_ratio(returns),
                var_95=returns.quantile(0.05),
                cvar_95=returns[returns <= returns.quantile(0.05)].mean(),
                beta=self._calculate_beta(returns, benchmark_returns),
                alpha=annual_return - self._calculate_beta(returns, benchmark_returns) * benchmark_returns.mean() * 252,
                tracking_error=float(tracking_error),
                start_date=self.config.start_date or datetime.now() - timedelta(days=365),
                end_date=self.config.end_date or datetime.now(),
                last_update=datetime.now()
            )
            
        except Exception as e:
            self.error_message = f"指标计算失败: {str(e)}"
            # 返回默认指标
            return StrategyMetrics(
                total_return=0.0, annual_return=0.0, volatility=0.0,
                sharpe_ratio=0.0, max_drawdown=0.0, win_rate=0.0,
                profit_loss_ratio=0.0, total_trades=0, profitable_trades=0,
                losing_trades=0, avg_trade_return=0.0, avg_holding_period=0.0,
                turnover_rate=0.0, information_ratio=0.0, calmar_ratio=0.0,
                sortino_ratio=0.0, var_95=0.0, cvar_95=0.0, beta=0.0,
                alpha=0.0, tracking_error=0.0,
                start_date=datetime.now(), end_date=datetime.now(),
                last_update=datetime.now()
            )
    
    def _calculate_max_drawdown(self, returns: pd.Series) -> float:
        """计算最大回撤"""
        cumulative = (1 + returns).cumprod()
        running_max = cumulative.expanding().max()
        drawdown = (cumulative - running_max) / running_max
        return float(drawdown.min())
    
    def _calculate_sortino_ratio(self, returns: pd.Series) -> float:
        """计算索提诺比率"""
        downside_returns = returns[returns < 0]
        if len(downside_returns) == 0:
            return 0.0
        if HAS_NUMPY:
            downside_deviation = float(downside_returns.std() * np.sqrt(252))
            mean_return = float(returns.mean())
            return float(mean_return * np.sqrt(252) / downside_deviation if downside_deviation > 0 else 0.0)
        else:
            downside_deviation = float(downside_returns.std() * (252 ** 0.5))
            mean_return = float(returns.mean())
            return float(mean_return * (252 ** 0.5) / downside_deviation if downside_deviation > 0 else 0.0)
    
    def _calculate_beta(self, returns: pd.Series, benchmark_returns: pd.Series) -> float:
        """计算贝塔系数"""
        if len(returns) != len(benchmark_returns) or len(returns) < 2:
            return 1.0
        if HAS_NUMPY:
            returns_array = returns.values
            benchmark_array = benchmark_returns.values
            cov_matrix = np.cov(returns_array, benchmark_array)
            covariance = float(cov_matrix[0][1])  # 使用列表索引而不是元组
            benchmark_variance = float(np.var(benchmark_array))
        else:
            # 简化的协方差和方差计算
            mean_returns = float(returns.mean())
            mean_benchmark = float(benchmark_returns.mean())
            diff_returns = returns - mean_returns
            diff_benchmark = benchmark_returns - mean_benchmark
            # 计算协方差
            cov_result = (diff_returns * diff_benchmark).mean()
            if pd.isna(cov_result):
                covariance = 0.0
            else:
                try:
                    # 使用pd.to_numeric安全转换，处理可能的Timedelta类型
                    cov_numeric = pd.to_numeric(cov_result, errors='coerce')
                    if pd.isna(cov_numeric):
                        covariance = 0.0
                    else:
                        covariance = float(cov_numeric)
                except (ValueError, TypeError):
                    covariance = 0.0
            benchmark_variance = float((diff_benchmark ** 2).mean())
        return float(covariance / benchmark_variance if benchmark_variance > 0 else 1.0)
    
    def _calculate_turnover_rate(self) -> float:
        """计算换手率"""
        # 简化计算，基于再平衡频率
        frequency_map = {
            "daily": 252,
            "weekly": 52,
            "monthly": 12,
            "quarterly": 4
        }
        return frequency_map.get(self.config.rebalance_frequency, 12) * 0.3
    
    def get_factor_exposures(self) -> Dict[str, Dict[str, float]]:
        """
        获取因子暴露
        
        Returns:
            Dict[str, Dict[str, float]]: 因子暴露
        """
        return self._factor_exposures.copy()
    
    def get_factor_returns(self) -> Dict[str, pd.Series]:
        """
        获取因子收益
        
        Returns:
            Dict[str, pd.Series]: 因子收益序列
        """
        return self._factor_returns.copy()
    
    def get_portfolio_weights(self) -> Dict[str, float]:
        """
        获取投资组合权重
        
        Returns:
            Dict[str, float]: 投资组合权重
        """
        return self._portfolio_weights.copy()